package factory.one.controller;

import factory.one.entity.*;
import factory.one.pojo.common.Page;
import factory.one.pojo.common.SqlCondition;
import factory.one.service.*;
import factory.one.utils.SecurityUtil;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.sql.Types;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author sk.z
 * 2023/11/9
 **/
@Controller
@RequestMapping("/deliver")
public class DeliverController {

    private final OrderService orderService;
    private final BatchService batchService;
    private final ProductService productService;
    private final CustomService customService;
    private final CountService countService;
    private final DeliverService deliverService;
    private final ExportService exportService;
    private final DeliverItemService itemService;

    public DeliverController(OrderService orderService,
                             BatchService batchService,
                             SendService sendService,
                             ProductService productService,
                             CustomService customService,
                             CountService countService,
                             DeliverService deliverService,
                             ExportService exportService,
                             DeliverItemService itemService) {
        this.orderService = orderService;
        this.batchService = batchService;
        this.productService = productService;
        this.customService = customService;
        this.countService = countService;
        this.deliverService = deliverService;
        this.exportService = exportService;
        this.itemService = itemService;
    }

    @GetMapping("/list.html")
    public String listHtml(@RequestParam(defaultValue = "1") Integer page,
                           @RequestParam(defaultValue = "10") Integer size,
                           Model model) {
        SqlCondition condition = new SqlCondition("is_confirm = ?", true, Types.BOOLEAN); //已上产线
        List<Order> list = orderService.listByCondition(page, size, Collections.singletonList(condition));
        Integer count = orderService.countByCondition(Collections.singletonList(condition));
        trans(list);
        model.addAttribute("page", new Page<>(list, count, page, size));
        return "deliver/list";
    }

    @GetMapping("/send.html")
    public String sendHtml(@RequestParam Long orderId, Model model) {
        List<Batch> batchList = batchService.list(orderId);
        transBatch(batchList);
        Map<Long, Batch> batchMap = batchList.stream().collect(Collectors.toMap(Batch::getId, e -> e, (k1, k2) -> k1));
        List<Deliver> deliverList = deliverService.listInSending(orderId);

        if (CollectionUtils.isEmpty(deliverList)) {
            model.addAttribute("inSending", false);
            model.addAttribute("map", Collections.emptyMap());
        } else {
            model.addAttribute("inSending", true);
            Map<Deliver, List<DeliverItem>> map = new LinkedHashMap<>();
            for (Deliver deliver : deliverList) {
                List<DeliverItem> itemList = itemService.listByDeliver(deliver.getId());
                for (DeliverItem item : itemList) {
                    item.setProductName(batchMap.get(item.getBatchId()).getProductName());
                }
                map.put(deliver, itemList);
            }
            model.addAttribute("map", map);
        }
        model.addAttribute("order", orderService.getById(orderId));
        return "deliver/send";
    }

    @PostMapping("create")
    public synchronized String create(@RequestParam Long orderId, Model model) {
        List<Deliver> l = deliverService.listInSending(orderId);
        if (!CollectionUtils.isEmpty(l)) {
            return sendHtml(orderId, model);
        }

        Deliver deliver = new Deliver();
        deliver.setOrderId(orderId);
        deliver.setSequence(0);
        deliver.setNumber(0);
        deliver.setCreateUser(SecurityUtil.getUserName());
        deliver.setCreateTime(new Date());
        deliver.setStatus(1);
        Long deliverId = deliverService.add(deliver);
        deliver.setId(deliverId);

        List<Batch> batchList = batchService.list(orderId);
        transBatch(batchList);
        List<DeliverItem> itemList = new ArrayList<>();
        for (Batch batch : batchList) {
            DeliverItem item = new DeliverItem();
            item.setDeliverId(deliverId);
            item.setBatchId(batch.getId());
            item.setNumber(0);
            item.setProductName(batch.getProductName());
            Long itemId = itemService.add(item);
            item.setId(itemId);
            itemList.add(item);
        }

        model.addAttribute("inSending", true);
        Map<Deliver, List<DeliverItem>> map = new LinkedHashMap<>();
        map.put(deliver, itemList);
        model.addAttribute("map", map);

        model.addAttribute("order", orderService.getById(orderId));

        return "deliver/send";
    }

    @ResponseBody
    @PostMapping("/add")
    public Boolean add(@RequestParam Long id, @RequestParam Integer num, @RequestParam Integer sum) {
        return itemService.updateNumberById(id, sum) > 0;
    }

    @PostMapping("/complete")
    public String complete(@RequestParam Long id, RedirectAttributes attributes){
        Deliver deliver = deliverService.getById(id);
        int i = deliverService.updateStatus(id, 2);
        int j = deliverService.setSequence(id,deliver.getOrderId());
        countService.forDeliver(deliver.getOrderId());
//        attributes.addAttribute("orderId",deliver.getOrderId());
//        return "redirect:detail.html";
        return "redirect:list.html";
    }

    @GetMapping("/detail.html")
    public String detailHtml(@RequestParam Long orderId, Model model) {
        Order order = orderService.getById(orderId);
        model.addAttribute("order", order);

        List<Batch> batchList = batchService.list(orderId);
        transBatch(batchList);
        model.addAttribute("batchList", batchList);
        Map<Long, String> batchMap = batchList.stream().collect(Collectors.toMap(Batch::getId, Batch::getProductName, (k1, k2) -> k1));

        List<Deliver> deliverList = deliverService.listHistory(orderId);
        Map<Deliver, List<DeliverItem>> map = new LinkedHashMap<>();
        for (Deliver deliver : deliverList) {
            List<DeliverItem> itemList = itemService.listByDeliver(deliver.getId());
            for (DeliverItem item : itemList) {
                item.setProductName(batchMap.get(item.getBatchId()));
            }
            map.put(deliver, itemList);
        }
        model.addAttribute("map", map);
        return "deliver/detail";
    }

    @GetMapping("/export")
    public void export(@RequestParam Long orderId, HttpServletResponse response) throws IOException {
        Order order = orderService.getById(orderId);
        response.setContentType("application/msexcel");
        response.setHeader("Content-Disposition", String.format("attachment;filename=\"%s\"", URLEncoder.encode(order.getCode() + "发货详单.xlsx", "utf-8")));
        ServletOutputStream outputStream = response.getOutputStream();
        Workbook workbook = exportService.exportDelivery(orderId);
        workbook.write(outputStream);
        workbook.close();
        outputStream.close();
    }

    private void trans(List<Order> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        for (Order order : list) {
            Custom custom = customService.getById(order.getCustomId());
            order.setCustomName(custom.getName());
        }
    }

    private void transBatch(List<Batch> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        for (Batch batch : list) {
            Product product = productService.getById(batch.getProductId());
            batch.setProductName(product.getName());
            batch.setAmount(batch.getSendNum() * batch.getPrice());
            batch.setProduceGap(Math.max(0, batch.getOrderNum() - batch.getProduceNum()));
            batch.setSendGap(Math.max(0, batch.getOrderNum() - batch.getSendNum()));
        }
    }

}
